#!/usr/bin/env python
# -*- coding: utf-8 -*-


import tornado.web
import hmac
import uuid
import json
import httpagentparser
import hashlib
from config import etc
from utils import log

def generate_id() :
    new_id = hashlib.sha256( etc.session_secret + str(uuid.uuid4()) )
    return new_id.hexdigest()


def generate_hmac( ssid ) :
    return hmac.new( ssid, etc.session_secret, hashlib.sha256 ).hexdigest()


def Session( request ) :

    @tornado.web.authenticated
    def Process( handler, *args ) :
        #请求前重建Session数据的过程
        #
        #执行原本请求的方法
        request( handler, *args )
        #请求完成后保存Session数据的过程
        if handler.ss_user != None:
            handler.ss_store.replace( handler.ss_user )
    return Process


def Guest( request ) :

    @tornado.web.asynchronous
    def Process( handler, *args ) :
        #请求前检验Session数据的过程
        try:
            handler.ss_ua = httpagentparser.detect( handler.request.headers["User-Agent"] )
            log.i( '[RIP:%s][U-A:%s]' % (handler.request.headers['X-Real-Ip'],handler.ss_ua) )
        except Exception as e :
            log.exp(e)
            res = { 'idx':-1, 'ret':-1, 'msg':etc.err_op_fail, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        #执行原本请求的方法
        try:
            request( handler, *args )
        except Exception as e:
            log.exp(e)
            res = { 'idx':-1, 'ret':-2, 'msg':etc.err_500, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        #请求完成后保存Session数据的过程
    return Process


def ApiGuest( request ) :

    @tornado.web.asynchronous
    def Process( handler, *args ) :
        #请求前检验Session数据的过程
        try:
            handler.ssid = handler.get_cookie( etc.cookie_ssid )
            handler.ss_ua = handler.request.headers["User-Agent"]
            handler.ss_ver = handler.get_cookie( etc.cookie_ver )
            if not handler.ssid :
                log.w( '[U-A:%s] no_ssid' % handler.ss_ua )
                res = { 'idx':-1, 'ret':-1, 'msg':etc.err_op_fail, 'res':{} }
                handler.write( json.dumps(res) )
                handler.finish()
                return
            postData = handler.get_argument( 'postData', default=None )
            # if postData is None ,json.loads() will arise a Exception
            if postData :
                paramsJson = json.loads(postData)
            handler.ss_idx = paramsJson['idx'] if postData else 0
            handler.ss_params = paramsJson['params'] if postData else None
            log.i( '[RIP:%s][U-A:%s][idx:%s][ver:%s][params:-]' % (handler.request.headers['X-Real-Ip'],handler.ss_ua,handler.ss_idx,handler.ss_ver) )
            log.i( '[ssid:%s] [check:%s] [verify:%s]' % (handler.ssid,handler.get_secure_cookie( etc.cookie_check ),handler.get_secure_cookie( etc.cookie_verify )) )
        except Exception as e :
            log.exp(e)
            res = { 'idx':-1, 'ret':-2, 'msg':etc.err_op_fail, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        #执行原本请求的方法
        try:
            request( handler, *args )
        except Exception as e:
            log.exp(e)
            res = { 'idx':-1, 'ret':-4, 'msg':etc.err_500, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        #请求完成后保存Session数据的过程
    return Process


def ApiHost( request ) :

    @tornado.web.asynchronous
    def Process( handler, *args ) :
        #请求前检验Session数据的过程
        try:
            handler.ssid = handler.get_cookie( etc.cookie_ssid )
            handler.ss_ua = handler.request.headers["User-Agent"]
            handler.ss_ver = handler.get_cookie( etc.cookie_ver )

            log.i(handler.request.cookies)

            if not handler.ssid :
                log.w( '[U-A:%s] no_ssid' % handler.ss_ua )
                res = { 'idx':-1, 'ret':-1, 'msg':etc.err_op_fail, 'res':{} }
                handler.write( json.dumps(res) )
                handler.finish()
                return
            postData = handler.get_argument( 'postData', default=None )
            # if postData is None ,json.loads() will arise a Exception
            if postData :
                paramsJson = json.loads(postData)
            handler.ss_idx = paramsJson['idx'] if postData else 0
            handler.ss_params = paramsJson['params'] if postData else None
            #log.i(" ~~~~~~~~~~~~~~~~~~~~ %d" % (postData['idx']))
            log.i( '[RIP:%s][U-A:%s][ssid:%s][idx:%s][ver:%s][params:-]' % (handler.request.headers['X-Real-Ip'],handler.ss_ua,handler.ssid,handler.ss_idx,handler.ss_ver) )
        except Exception as e :
            log.exp(e)
            res = { 'idx':-1, 'ret':-2, 'msg':etc.err_op_fail, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        handler.current_user
        if handler.ss_user == None :
            log.w( '[U-A:%s] signin_required' % handler.ss_ua )
            res = { 'idx':-1, 'ret':-3, 'msg':etc.err_signin_requied, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        #执行原本请求的方法
        try:
            request( handler, *args )
        except Exception as e:
            log.exp(e)
            res = { 'idx':-1, 'ret':-4, 'msg':etc.err_500, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
        #请求完成后保存Session数据的过程
        try:
            if handler.ss_user != None:
                handler.ss_store.replace( handler.ssid, handler.ss_user )
        except Exception as e:
            log.exp(e)
            res = { 'idx':-1, 'ret':-4, 'msg':etc.err_500, 'res':{} }
            handler.write( json.dumps(res) )
            handler.finish()
            return
    return Process


class BaseSessionStore:
    """Base class for session stores"""
    def contains( self, key ) :
        raise NotImplementedError

    def cleanup( self ) :
        raise NotImplementedError

    def get( self, ssid ) :
        raise NotImplementedError

    def set( self, ssid, ss_user ) :
        raise NotImplementedError

    def delete( self, ssid ) :
        raise NotImplementedError

    def replace( self, ss_user ) :
        raise NotImplementedError


class InvalidSessionException(Exception) :
    pass


